package com.opages.mvc.adapter.nacos.discovery;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.opages.mvc.adapter.common.condition.annotation.ConditionalOnMissingBean;
import com.opages.mvc.adapter.common.client.ServiceInstance;
import com.opages.mvc.adapter.common.client.discovery.DiscoveryClient;
import com.opages.mvc.adapter.nacos.model.NacosDiscoveryProperties;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author daizhong.liu
 * @create 2020-06-09 17:16
 **/
@ConditionalOnMissingBean(DiscoveryClient.class)
public class NacosDiscoveryClient implements DiscoveryClient {

    private final NacosDiscoveryProperties nacosDiscoveryProperties;

    public NacosDiscoveryClient(NacosDiscoveryProperties nacosDiscoveryProperties) {
        this.nacosDiscoveryProperties = nacosDiscoveryProperties;
    }

    @Override
    public List<ServiceInstance> getInstances(String serviceId)  {
        String group = nacosDiscoveryProperties.getGroup();
        try {
            List<Instance> instances = nacosDiscoveryProperties.namingServiceInstance()
                    .selectInstances(serviceId, group, true);
            return hostToServiceInstanceList(instances, serviceId);
        } catch (NacosException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public ServiceInstance chooseServer(String serviceId) {
        List<ServiceInstance> instances = getInstances(serviceId);
        ILoadBalancer balancer = new BaseLoadBalancer();
        List<Server> nacosServiceInstances = new ArrayList<>();
        instances.stream().forEach(a -> nacosServiceInstances.add((NacosServiceInstance)a));
        balancer.addServers(nacosServiceInstances);
        NacosServiceInstance choosedServer = (NacosServiceInstance)balancer.chooseServer(null);
        return choosedServer;
    }




    public List<ServiceInstance> hostToServiceInstanceList(
            List<Instance> instances, String serviceId) {
        List<ServiceInstance> result = new ArrayList<>(instances.size());
        for (Instance instance : instances) {
            ServiceInstance serviceInstance = hostToServiceInstance(instance, serviceId);
            if (serviceInstance != null) {
                result.add(serviceInstance);
            }
        }
        return result;
    }
    public ServiceInstance hostToServiceInstance(Instance instance, String serviceId) {
        if (instance == null || !instance.isEnabled() || !instance.isHealthy()) {
            return null;
        }
        NacosServiceInstance nacosServiceInstance = new NacosServiceInstance(instance.getIp(),instance.getPort());
        nacosServiceInstance.setServiceId(serviceId);

        Map<String, String> metadata = new HashMap<>();
        metadata.put("nacos.instanceId", instance.getInstanceId());
        metadata.put("nacos.weight", instance.getWeight() + "");
        metadata.put("nacos.healthy", instance.isHealthy() + "");
        metadata.put("nacos.cluster", instance.getClusterName() + "");
        metadata.putAll(instance.getMetadata());
        nacosServiceInstance.setMetadata(metadata);

        if (metadata.containsKey("secure")) {
            boolean secure = Boolean.parseBoolean(metadata.get("secure"));
            nacosServiceInstance.setSecure(secure);
        }
        return nacosServiceInstance;
    }
}
